<template>
  <Cesium v-if="sceneStore.sceneDetail" />
  <div class="editor-wrapper" :class="sceneStore.preview ? 'editor-preview' : ''">
    <Header :activity-id="sceneId" @release="createShareDialogShow = true" />
    <LayerTool v-if="sceneStore.leftPanelActive !== 'panel'"></LayerTool>
    <div class="editor-main">
      <Sidebar />
      <div class="panel-container">
        <LeftPanel
          :title="titleMap[sceneStore.leftPanelActive] || ''"
          :show-header="getShowHeader"
          @toggleVisible="toggleVisible('leftPanel')"
        >
          <div :style="{ height: `${sceneStore.topHeight}` }">
            <Info :data="basicDetailData" v-if="sceneStore.leftPanelActive === 'info'" />
            <Panel v-if="sceneStore.leftPanelActive === 'panel'" />
            <Effect v-if="sceneStore.leftPanelActive === 'effect'" />
            <BottomPlate v-if="sceneStore.leftPanelActive === 'bottomPlate'" />
            <Resource
              v-if="sceneStore.leftPanelActive === 'import'"
              :data="resourceData.list"
              @refresh="handleRefresh"
            />
          </div>
          <div
            v-if="sceneStore.layerPanelVisible"
            class="bottom-half"
            @pointerdown="onPointerDown"
            @pointermove="onPointerMove"
            @pointerup="onPointerUp"
          >
            <div class="resizer"></div>
            <Layer @toggleVisible="toggleVisible('layer')" />
          </div>
        </LeftPanel>
        <RightPanel>
          <Attribute v-if="sceneStore.specialEffectVisible && sceneStore.selLayer" />
          <GlobalEffect v-else />
        </RightPanel>
      </div>
    </div>
  </div>
  <CreateShare
    v-if="createShareDialogShow"
    v-model="createShareDialogShow"
    :scene="sceneStore.sceneDetail"
    @close-handle="createShareCloseHandle"
    @update="updateSceneDetail"
  ></CreateShare>
  <DivEditMask v-if="sceneStore.divEditLayerName" />
</template>

<script setup lang="ts">
import { getResourceList } from '@/api/resource';
import { IResource } from '@/api/resource/types';
import { getSceneConfigList, getSceneDetail, insertSceneViewCount } from '@/api/scene';
import DivEditMask from '@/components/gis-div/drag-mask.vue';
import RightPanel from '@/components/panel-wapper/right-panel.vue';
import { clearLayerClickCallbackMap, clearLayerMap, clearModelReadyMap } from '@/service';
import { layerRequestInsMap } from '@/service/effect';
import { useSceneStore } from '@/store/scene';
import { getFileNameByUrl } from '@/utils';
import { getInitGlobalEffectData } from '@/views/enum/global-effect';
import CreateShare from '@/views/scene/create-share/index.vue';
import { useRequest } from '@jl/common/composable';
import { useRoute } from 'vue-router';
import BottomPlate from './components/bottom-plate/index.vue';
import Cesium from './components/cesium.vue';
import Effect from './components/effect/index.vue';
import GlobalEffect from './components/global-effect/index.vue';
import Header from './components/header.vue';
import Info from './components/info/index.vue';
import LayerTool from './components/layer-tool/index.vue';
import Layer from './components/layer/index.vue';
import LeftPanel from './components/left-panel-dialog/index.vue';
import Panel from './components/panel/index.vue';
import Resource from './components/resource/index.vue';
import Sidebar from './components/sidebar.vue';
import Attribute from './components/attribute/index.vue';

defineOptions({
  name: 'SceneDetail',
});

const sceneStore = useSceneStore();
const route = useRoute();
const sceneId = ref<string>('');
const createShareDialogShow = ref(false);

const GlobalEffectSetting = ref(getInitGlobalEffectData());

const resizing = ref(false);
const titleMap: any = {
  info: '场景信息',
  bottomPlate: '底板',
  effect: '特效组件',
  panel: '面板组件',
  import: '导入资源管理',
};

const getShowHeader = computed(() => {
  if (sceneStore.layerPanelVisible && !sceneStore.leftPanelActive) {
    return false;
  }
  return true;
});

const { run: basicDetailRun, data: basicDetailData } = useRequest<any, API.Scene.Scene | null>(
  getSceneDetail,
  null
);
const { run: configRun, data: configData } = useRequest<any, any>(getSceneConfigList, null);
const { run: resourceRun, data: resourceData } = useRequest<any, API.Base.ResponsePage<IResource>>(
  getResourceList,
  { count: 0, list: [] }
);

const disableRightClick = (event: any) => {
  event.preventDefault();
};

const disableF12 = (event: any) => {
  if (event.keyCode === 123) {
    event.preventDefault(); // 阻止默认F12键行为
  }
};

onMounted(async () => {
  if (route.path.indexOf('scene/preview') > -1 || route.path.indexOf('scene/shareview') > -1) {
    sceneStore.preview = true;
    insertSceneViewCount({ params: { actId: route.params.id } });
  }
  sceneId.value = route.params.id as string;
  await basicDetailRun({ params: { activityId: sceneId.value } });
  sceneStore.sceneDetail = basicDetailData.value;
  if (route.path.indexOf('scene/detail') > -1) {
    sceneStore.getVersionList();
    resourceRun({
      params: {
        index: 1,
        pageSize: 10000,
      },
    });
    window.addEventListener('keydown', exit);
  }
  // 是否禁用右键和F12
  if (process.env.VUE_RIGHT_BUTTON_AND_F12_USABLE === 'DISABLE') {
    document.addEventListener('contextmenu', disableRightClick);
    document.addEventListener('keydown', disableF12);
  }
  initGlobalEffect();
  const savedTopHeight = localStorage.getItem('topHeight');
  if (savedTopHeight) {
    sceneStore.topHeight = savedTopHeight;
  }
});

onBeforeUnmount(() => {
  if (process.env.VUE_RIGHT_BUTTON_AND_F12_USABLE === 'DISABLE') {
    document.removeEventListener('contextmenu', disableRightClick);
    document.removeEventListener('keydown', disableF12);
  }
  const { cimInstance } = window;
  cimInstance.api.clearOrbitControl();
  sceneStore.layerList.forEach((layer: any) => {
    cimInstance.api.destroyLayer(layer.layerName);
  });
  sceneStore.layerTree = [];
  sceneStore.layerList = [];
  sceneStore.selectedLayerNode = null;
  sceneStore.sourceType = '';

  sceneStore.onlineMapSels = [];
  sceneStore.isCimupComplete = false;
  sceneStore.leftPanelActive = '';
  sceneStore.preview = false;
  sceneStore.leftPanelVisible = false;
  sceneStore.mapPanelVisible = false;
  sceneStore.sceneDetail = null;
  sceneStore.mapCameraHeight = 100000;
  sceneStore.versionList = [];
  sceneStore.globalEffectSetting = null;
  clearModelReadyMap();
  clearLayerMap();
  clearLayerClickCallbackMap();
  sceneStore.selLayer = null;
  sceneStore.specialEffectVisible = false;
  [...layerRequestInsMap.keys()].forEach((layerName) => {
    const ins: any = layerRequestInsMap.get(layerName);
    ins.destroy();
    layerRequestInsMap.delete(layerName);
  });

  window.removeEventListener('keydown', exit);
});

/**
 * configJson数据映射到全局特效数据
 */
function initGlobalEffect() {
  if (!sceneStore.sceneDetail) return;
  const configJson = sceneStore.sceneDetail.configJson
    ? JSON.parse(sceneStore.sceneDetail.configJson)
    : null;
  const mapObject = configJson?.cimup?.mapObject || null;
  if (mapObject) {
    // 光源
    if (mapObject?.light) {
      const lightSource = GlobalEffectSetting.value.light.lightSource;
      GlobalEffectSetting.value.light.lightSource = Object.assign(
        lightSource,
        configJson.cimup.mapObject.light
      );
    }
    // 光照设置
    if (mapObject?.scene?.clockConfig) {
      GlobalEffectSetting.value.light.illumination.shouldAnimate =
        !!mapObject.scene.clockConfig.shouldAnimate;
      GlobalEffectSetting.value.light.illumination.currentTime =
        mapObject.scene.clockConfig.currentTime;
    }
    // 后处理
    const postProcess = configJson?.cimup?.mapObject?.postProcess || [];
    postProcess.forEach((item: any) => {
      GlobalEffectSetting.value.process.forEach((v: any) => {
        if (item.name === v.key) {
          const { name, ...param } = item;
          v.value = Object.assign(v.value, param);
        }
      });
    });
    // 背景
    const skyBox =
      (mapObject.layers || []).find((item: any) => item.skyBoxBGConfig || item.type === 'skybox') ||
      null;
    if (skyBox) {
      // 背景图
      if (skyBox.skyBoxBGConfig?.showImage) {
        GlobalEffectSetting.value.background.backgroundType = 'bkgImg';
        const imgUrl: string = skyBox.skyBoxBGConfig.dataSourceUrl || '';
        (GlobalEffectSetting.value.background.backgroundImage as any) = {
          name: getFileNameByUrl(imgUrl),
          url: imgUrl,
        };
      } else {
        // 天空盒回显
        GlobalEffectSetting.value.background.backgroundType = 'SkyBox';
        const url = skyBox.dayPart.evening.negativeX;
        (GlobalEffectSetting.value.background.skybox as any) = {
          name: getFileNameByUrl(url.split('/evening')[0]),
          param: skyBox.dayPart,
        };
      }
    }
    // 天气
    const weather = configJson?.cimup?.mapObject?.weather || [];
    if (Array.isArray(weather)) {
      weather.forEach((item: any) => {
        const { type, ...param } = item;
        GlobalEffectSetting.value.environment.normal.forEach((v: any) => {
          if (type === v.key) {
            v.params = Object.assign(v.params, param);
          }
        });
      });
      const cloudLayer =
        (mapObject.layers || []).find((item: any) => item.type === 'rectangle') || null;
      if (cloudLayer) {
        GlobalEffectSetting.value.environment.other.forEach((item: any) => {
          // 大气
          if (item.key === 'sky') {
            item.params.enable = !!mapObject?.scene?.skyAtmosphere;
          }
          // 云层
          if (item.key === 'cloudLayer' && cloudLayer) {
            item.params.enable = true;
          }
        });
      }
    }
  } else {
    // 默认值
    GlobalEffectSetting.value.environment.normal.forEach((item: any) => {
      if (item.key === 'sunny') {
        item.params.enable = true;
      }
    });
  }
  sceneStore.globalEffectSetting = GlobalEffectSetting.value;
}

function exit(event?: any) {
  if ((event && event.keyCode !== 27) || route.path.indexOf('scene/preview') > -1) {
    return;
  }
  sceneStore.preview = false;
}

function handleRefresh() {
  resourceRun({
    params: {
      index: 1,
      pageSize: 10000,
    },
  });
}

function createShareCloseHandle() {
  createShareDialogShow.value = false;
}

function updateSceneDetail() {
  basicDetailRun({ params: { activityId: sceneId.value } });
}

/**
 * 左侧面板关闭按钮执行逻辑
 * @param type
 */
function toggleVisible(type: string) {
  if (sceneStore.layerPanelVisible && sceneStore.leftPanelActive) {
    if (type === 'leftPanel') {
      sceneStore.leftPanelActive = '';
      sceneStore.topHeight = '0px';
    }
  } else if (sceneStore.layerPanelVisible) {
    if (type === 'layer') {
      sceneStore.leftPanelVisible = false;
      sceneStore.topHeight = 'calc(100% - 28px)';
    }
  } else if (sceneStore.leftPanelActive) {
    if (type === 'leftPanel') {
      sceneStore.leftPanelVisible = false;
      sceneStore.topHeight = 'calc(100% - 28px)';
      sceneStore.leftPanelActive = '';
    } else {
      sceneStore.topHeight = 'calc(100% - 28px)';
    }
  } else {
    sceneStore.leftPanelVisible = false;
    sceneStore.leftPanelActive = '';
    sceneStore.topHeight = 'calc(100% - 28px)';
  }
}

// 拖拽调整左侧宽度
const onPointerDown = (e: PointerEvent) => {
  resizing.value = true;
  (e.target as any).setPointerCapture(e.pointerId);
};
const onPointerMove = (e: PointerEvent) => {
  if (resizing.value) {
    sceneStore.topHeight = e.clientY + 'px';
  }
};
const onPointerUp = (e: PointerEvent) => {
  resizing.value = false;
  (e.target as any).releasePointerCapture(e.pointerId);
  localStorage.setItem('topHeight', `${sceneStore.topHeight}`);
};

watch(
  () => sceneStore.specialEffectVisible,
  () => {
    if (sceneStore.specialEffectVisible) {
      sceneStore.mapPanelVisible = false;
    }
  }
);
</script>

<style lang="less" scoped>
.editor-wrapper {
  position: absolute;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  color: #fff;
  font-size: 14px;
  opacity: 1;
  transition: opacity 0.4s ease-in;
  pointer-events: none;
  overflow: hidden;

  .editor-main {
    position: relative;
    width: 60px;
    height: calc(100vh - 60px);
    pointer-events: initial;
    .panel-container {
      position: relative;
      height: 100%;
      display: flex;
      flex-direction: column;
      .bottom-half {
        flex: 1;
        background-color: #2f333b;
        .resizer {
          height: 4px;
        }
      }
    }
    :deep(.el-form) {
      --el-fill-color-blank: rgba(36, 44, 52, 0.3);
      --el-border-color: rgba(69, 72, 81, 0.6);
      --el-text-color-regular: #fff;
      --el-border-radius-base: 4px;
      --el-disabled-bg-color: rgba(36, 44, 52, 0.3);
      --el-disabled-border-color: rgba(69, 72, 81, 0.6);
      .el-input-number {
        &.el-slider__input {
          .el-input-number__decrease,
          .el-input-number__increase {
            background: rgba(36, 44, 52, 0.3);
            border: none;
          }
          .el-input__wrapper {
            background: rgba(36, 44, 52, 0.3);
          }
        }
      }
      .el-slider {
        --el-slider-runway-bg-color: #2f333b;
        --el-slider-button-size: 12px;
      }
      .el-input__inner ::placeholder {
        color: #9a9a9a;
      }
      .el-select {
        width: 100%;
      }
    }
  }
}
.editor-preview {
  opacity: 0;
  :deep(.editor-header),
  :deep(.editor-main) {
    pointer-events: none;
  }
}

.editor-hidden {
  left: -276px;
}
</style>
